home *** CD-ROM | disk | FTP | other *** search
/ Windows Shareware Gold / Windows Shareware Gold Volume 3 Number 1 (Sherburne Knowledge Systems) (1991).iso / utils / f3106 / crdprt.c < prev    next >
C/C++ Source or Header  |  1990-11-01  |  13KB  |  313 lines

  1. /*
  2.  * crdprt.c - version 2.1 - November 1st, 1990
  3.  *
  4.  * crdprint - print a Microsoft Windows cardfile
  5.  *
  6.  * This program will print a cardfile in a simple fashion on any ASCII 
  7.  * printer.  It does not bother drawing the cute (and timeconsuming) boxes 
  8.  * around the cards.
  9.  *
  10.  * Art Zemon   July 12, 1986
  11.  *
  12.  * CompuServe:   72406,3275
  13.  * UUCP:   ucbvax!trwrb!felix!zemon
  14.  **************************************************************************
  15.  *
  16.  * Updated: Munjal M. July 21, 1990
  17.  * CompuServe:   76264,602
  18.  **************************************************************************
  19.  *
  20.  * Updated   : Version 2.0 - September 5, 1990
  21.  *           : Rod Hutson... CompuServe 72411,564
  22.  *             (403) 461-2431 (Edmonton, Alberta, Canada)
  23.  * Changes   : couldn't get large cardfiles (90 cards, 19000+ bytes) to print
  24.  *             so changed design of program to use only one file handle and
  25.  *             track file position with a long variable instead... original
  26.  *             version used two file handles open simulataneously to maintain
  27.  *             file position.
  28.  *           : altered variable names to follow Windows-style Hungarian
  29.  *             notation (with some variations due mainly to old habits)
  30.  *           : added copious commenting for those who like such things
  31.  *           : ensured worked with WINDOWS 3.0 Cardfile files
  32.  **************************************************************************
  33.  *
  34.  * Updated   : Version 2.1 - November 1st, 1990
  35.  *           : Rod Hutson... CompuServe 72411,564
  36.  *             (403) 461-2431 (Edmonton, Alberta, Canada)
  37.  * Changes   : modified program to properly handle cardfile cards
  38.  *             containing graphic images; any card containing a standard
  39.  *             cardfile 'picture' graphic as well as standard text is
  40.  *             processed as if the graphic weren't there; if the card
  41.  *             contains only a graphic image or is blank, only the index 
  42.  *             line is processed; if the card contains text only, then 
  43.  *             it is processed normally;
  44.  *           : while modifying previous ver 2.0 for the above functionality,
  45.  *             I discovered a mistake in the card data structures... these 
  46.  *             are now corrected as described below.
  47.  *           : tested the resulting executable with cardfiles issued by
  48.  *             WUGNET, consisting of 100,000+ bytes, over 300 cards, and
  49.  *             many or most with some graphic image(s) on them
  50.  * NOTE      : rather than obsfucate the code to make it 'nice and tight',
  51.  *             I have left it loose and readable, and maybe even somewhat
  52.  *             unstructured (ie. no sub-function calls, etc).
  53.  **************************************************************************
  54.  */
  55.  
  56. #include <stdio.h>      /* provides NULL, SEEK_SET, etc */
  57. #include <stdlib.h>
  58.  
  59. #define TEXT_BUF    512     /* size of text buffer for card text */
  60. #define INDEX_TEXT  40      /* max length of index line string   */
  61. #define BYTE        char    /* a convenience, thats all          */
  62.  
  63. #ifndef NULL                /* lint told me NULL not declared,   */
  64.     #define NULL    0       /*   so I did this, just to be sure  */
  65. #endif
  66.  
  67. /**********************************************************/
  68. /* layout the data structures for a MicroSoft '.crd' file */
  69. /**********************************************************/
  70. /* file header structure */
  71. typedef struct {
  72.     char    acSigniture[3]; /* 3 bytes ... 'MGC' */
  73.     int     iNumCrds;       /* 2 bytes ... number of cards in cardfile */
  74. } sFILEHDR;              /* structure is 5 bytes long */
  75.  
  76. /* index data structure for each card */
  77. typedef struct {
  78.     int     aiFuture[3];                /* 6 bytes ... reserved for future   */
  79.     long    lOffset;                    /* 4 bytes ... card offset into file */
  80.     BYTE    bFlag;                      /* 1 byte  ... some kind of flag     */
  81.     char    acIndexText[INDEX_TEXT];    /* INDEX_TEXT bytes ... index line   */
  82.     BYTE    bNull;                      /* 1 byte  ... always '0' or NULL    */
  83. } sINDEXHDR;             /* structure is (12+INDEX_TEXT) bytes long */
  84.  
  85. /* if card contains text only, this structure applies to card data */
  86. typedef struct {
  87.     int     iLenBMap;       /* 2 bytes ... if no bitmap, always 0X0000     */
  88.     int     iLenText;       /* 2 bytes ... number of bytes in text strings */
  89. } sTEXTONLY;             /* structure is 4 bytes long */
  90.  
  91. void main (int argc, char **argv)
  92. {
  93.     /* we'll substitute this simple string for the graphics in Windows */ 
  94.     static char acSep[] = "════════════════════════════════════════";
  95.  
  96.     FILE            *hFile;             /* handle to current cardfile */
  97.  
  98.     sFILEHDR        sFileHdr;           /* file header variable */
  99.  
  100.     sINDEXHDR       sIndexHdr;          /* card index line variable */
  101.  
  102.     sTEXTONLY       sTextOnly;          /* text-only card body variable */
  103.  
  104.     unsigned char   acText[TEXT_BUF];   /* card body text buffer */
  105.  
  106.     unsigned int    iCard,              /* current card count */
  107.                     iCardFile,          /* current cardfile count */
  108.                     iCheck,             /* dummy error variable */
  109.                     iTextLength;        /* dummy text length variable */
  110.  
  111.     long            lCurrPos,           /* current file position */
  112.                     lTmpPos;            /* dummy file position variable */
  113.  
  114.     /* if command line did not include cardfile(s) to print out, msg & exit */
  115.     if (argc < 2) {
  116.         fputs ("CrdPrt V2.1, November 1st, 1990\n\n", stderr);
  117.         fputs ("Usage: CrdPrt {card-file} [{card-file-2}...]\n", stderr);
  118.         fputs ("\t{card-file} is any DOS file-spec including wild-cards.\n\n", stderr);
  119.         fputs ("\tCrdPrt will display one or several cardfile(s) in a simple format\n", stderr);
  120.         fputs ("\t  without wasting valuable time doing fancy graphics.\n", stderr);
  121.         exit (1);
  122.     }
  123.  
  124.     /* do this until no more cardfile files to process */
  125.     iCardFile = 0;
  126.     while (++iCardFile < argc) {
  127.  
  128.         /* if cannot open cardfile, msg & exit */
  129.         if ((hFile = fopen (argv[iCardFile], "r")) == NULL) {
  130.             perror (argv[iCardFile]);
  131.             exit (1);
  132.         }
  133.         fclose (hFile);
  134.  
  135.         /* reopen the file for 'read-binary' access */
  136.         hFile = fopen (argv[iCardFile], "rb");
  137.  
  138.         /* read current cardfile file header into appropriate structure */
  139.         iCheck = fread ((void *) &sFileHdr, sizeof (sFILEHDR), 1, hFile);
  140.  
  141.         /* if we read incorrect number of records, msg & exit */
  142.         if (iCheck != 1) {
  143.             perror ("Error reading file header");
  144.             fclose (hFile);
  145.             exit (1);
  146.         }
  147.  
  148.         /* initialize current position in file to origin */
  149.         lCurrPos = ftell (hFile);
  150.  
  151.         /* for current cardfile, go thru each card & display/print text */
  152.         for (iCard = 1; iCard <= sFileHdr.iNumCrds; ++iCard) {
  153.  
  154.             /* go to file offset of previous card index info */
  155.             fseek (hFile, lCurrPos, SEEK_SET);
  156.  
  157.             /* get current index line data */
  158.             iCheck = fread (&sIndexHdr, sizeof (sINDEXHDR), 1, hFile);
  159.  
  160.             /* if we read incorrect number of records, msg & exit */
  161.             if (iCheck != 1) {
  162.                 perror ("Error reading cardfile index text");
  163.                 fclose (hFile);
  164.                 exit (1);
  165.             }
  166.  
  167.             /* note current file position for later */
  168.             lCurrPos = ftell (hFile);
  169.  
  170.             /* go to file offset where this card is located */
  171.             iCheck = fseek (hFile, sIndexHdr.lOffset, SEEK_SET);
  172.  
  173.             /* if fseek() did not return a 0, msg & exit */
  174.             if (iCheck) {
  175.                 perror ("Error seeking card location in file");
  176.                 fclose (hFile);
  177.                 exit (1);
  178.             }
  179.  
  180.             /* note start of this card for later */
  181.             lTmpPos = ftell (hFile);
  182.  
  183.             /* assuming current card is text only, read first four bytes */
  184.             iCheck = fread ((void *) &sTextOnly, sizeof (sTEXTONLY), 1, hFile);
  185.  
  186.             /********************** debugging stuff ************************/
  187.             /* ******* uncomment if you want to see progress details *******/
  188.             /*
  189.             fprintf (stderr, "iCard=%x iCheck=%x iLenBMap=%x iLenText=%x\n", 
  190.                             iCard, iCheck, sTextOnly.iLenBMap, 
  191.                             sTextOnly.iLenText);
  192.             getchar ();
  193.             */
  194.             /***************************************************************/
  195.  
  196.             /* if we read incorrect number of records, msg & exit */
  197.             if (iCheck != 1) {
  198.                 perror ("Error reading first card body data bytes");
  199.                 fclose (hFile);
  200.                 exit (1);
  201.             }
  202.  
  203.             /* if first two bytes are 0, then no bitmap */
  204.             if (sTextOnly.iLenBMap == 0) {
  205.  
  206.                 /* could still be a pure text-bearing card, so check */
  207.                 if (sTextOnly.iLenText != 0) {
  208.  
  209.                     /* okay, there IS some card body text, so process it */
  210.                     if (sTextOnly.iLenText < TEXT_BUF) {
  211.  
  212.                         /* read designated number of card body text chars */
  213.                         iCheck = fread (acText, 1, sTextOnly.iLenText, hFile);
  214.  
  215.                         /* if read incorrect number of chars, msg & exit */
  216.                         if (iCheck != sTextOnly.iLenText) {
  217.                             perror ("Error reading card body text");
  218.                             fclose (hFile);
  219.                             exit (1);
  220.                         }
  221.  
  222.                         /* write separate string to output */
  223.                         puts (acSep);
  224.  
  225.                         /* write index line to output */
  226.                         puts (sIndexHdr.acIndexText);
  227.  
  228.                         /* write card body text to output */
  229.                         fwrite (acText, 1, sTextOnly.iLenText, stdout);
  230.                         putchar ('\n');
  231.                     }
  232.                     else
  233.                         /* uh, oh... more than TEXT_BUF chars in card text */
  234.                         fputs ("**Error** Cardfile Text Too Long!\a\n", stderr);
  235.                 }
  236.             }
  237.             else {
  238.                 /* card contains bitmap of length sTextOnly.iLenBMap bytes */
  239.  
  240.                 /* skip graphic by moving to end of bitmap data for this card */
  241.                 iCheck = fseek (hFile, 
  242.                             (lTmpPos + (long) (10 + sTextOnly.iLenBMap)),
  243.                             SEEK_SET);
  244.  
  245.                 /* if fseek() failed, msg & exit */
  246.                 if (iCheck) {
  247.                     perror ("Error moving to end of card bitmap data");
  248.                     fclose (hFile);
  249.                     exit (1);
  250.                 }
  251.  
  252.                 /* back to card body text: read length of card text in bytes */
  253.                 iCheck = fread ((void *) &iTextLength, sizeof (int), 1, hFile);
  254.  
  255.                 /************ debugging stuff ***************/
  256.                 /***** uncomment to see progress details ****/
  257.                 /*
  258.                 fprintf (stderr, "iCheck=%x iTextLength=%x\n", 
  259.                             iCheck, iTextLength);
  260.                 getchar ();
  261.                 */
  262.                 /********************************************/
  263.  
  264.                 /* if we had a problem reading text length, msg & exit */
  265.                 if (iCheck != 1) {
  266.                     perror ("Error reading in card body text length");
  267.                     fclose (hFile);
  268.                     exit (1);
  269.                 }
  270.  
  271.                 /* check to see how many chars are in card body text */
  272.                 if (iTextLength != 0) {
  273.  
  274.                     /* not a blank card, so do your stuff! */
  275.                     if (iTextLength < TEXT_BUF) {
  276.  
  277.                         /* read designated number of card body text bytes */
  278.                         iCheck = fread (acText, 1, iTextLength, hFile);
  279.  
  280.                         /* if read incorrect number of bytes, msg & exit */
  281.                         if (iCheck != iTextLength) {
  282.                             perror ("Error reading card body text");
  283.                             fclose (hFile);
  284.                             exit (1);
  285.                         }
  286.  
  287.                         /* write separator string to output */
  288.                         puts (acSep);
  289.  
  290.                         /* write index line to output */
  291.                         puts (sIndexHdr.acIndexText);
  292.  
  293.                         /* write card body text to output */
  294.                         fwrite (acText, 1, iTextLength, stdout);
  295.                         putchar ('\n');
  296.                     }
  297.                     else
  298.                         /* card body text > TEXT_BUF chars in length */
  299.                         fputs ("**Error** Cardfile Text Too Long!\a\n", stderr);
  300.                 }
  301.             }
  302.         }
  303.  
  304.         /* write final separator string to output, & close current cardfile */
  305.         puts (acSep);
  306.         fclose (hFile);
  307.     }
  308.  
  309.     /* we're outa here! */
  310.     exit (0);
  311. }
  312.  
  313.